package com.atguigu.jxc.log;
import com.atguigu.jxc.dao.LogDao;
import com.atguigu.jxc.dao.UserDao;
import com.atguigu.jxc.entity.User;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Expression;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
@Aspect
public class LogAspect {
    @Autowired
    UserDao userDao;
    @Autowired
    LogDao logDao;

    @Transactional
    @Around(value = "@annotation(com.atguigu.jxc.log.Log)")
    public Object log(ProceedingJoinPoint point){
        Object[] args = point.getArgs();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Log log = signature.getMethod().getAnnotation(Log.class);
        String value = parseExpression(log.value(),point);
        String date = log.logDate();
        LogType logType = log.logType();
        User user = userDao.findUserByName((String) SecurityUtils.getSubject().getPrincipal());
        try {
            Object proceed = point.proceed(args);
            if(proceed instanceof Boolean &&(Boolean) proceed){
                com.atguigu.jxc.entity.Log log1 = new com.atguigu.jxc.entity.Log();
                log1.setLogDate(isValidDate(date));
                log1.setUserId(user.getUserId());
                log1.setLogType(logType.name());
                log1.setContent(value);
                logDao.save(log1);
            }
            return proceed;
        } catch (Throwable throwable) {
            throw new RuntimeException();
        }
    }

    private Date isValidDate(String date){
        Date convertSuccess=null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        format.setLenient(false);
        try {
            convertSuccess=format.parse(date);
        } catch (ParseException e) {
            convertSuccess=new Date();
        }
        return convertSuccess;
    }
    /**
     * 动态解析表达式
     *
     * @param point
     * @return
     */
    private String parseExpression(String value, ProceedingJoinPoint point) {
        //1、准备解析器
        SpelExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression(value, new TemplateParserContext());
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable("args",point.getArgs());
        MethodSignature signature =(MethodSignature) point.getSignature();

        context.setVariable("method",signature.getMethod());
        return expression.getValue(context,String.class);
    }
}
